{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 8. 面向对象"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 8.1 面向对象基础\n",
    "\n",
    "- 类：一群有着相似性的事物的集合，这里对应 Python 的 class。\n",
    "    + 类，一群有着相同属性和函数的对象的集合。\n",
    "- 对象：集合中的一个事物，这里对应由 class 生成的某一个 object，比如代码中的 harry_potter_book。\n",
    "- 属性：对象的某个静态特征，比如上述代码中的 title、author 和 __context。\n",
    "- 函数：对象的某个动态能力，比如上述代码中的 intercept_context () 函数。\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "init function called\n",
      "Harry Potter\n",
      "J. K. Rowling\n",
      "77\n",
      "10\n"
     ]
    },
    {
     "ename": "AttributeError",
     "evalue": "'Document' object has no attribute '__context'",
     "output_type": "error",
     "traceback": [
      "\u001b[31m---------------------------------------------------------------------------\u001b[39m",
      "\u001b[31mAttributeError\u001b[39m                            Traceback (most recent call last)",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[1]\u001b[39m\u001b[32m, line 24\u001b[39m\n\u001b[32m     20\u001b[39m harry_potter_book.intercept_context(\u001b[32m10\u001b[39m)\n\u001b[32m     22\u001b[39m \u001b[38;5;28mprint\u001b[39m(harry_potter_book.get_context_length())\n\u001b[32m---> \u001b[39m\u001b[32m24\u001b[39m \u001b[38;5;28mprint\u001b[39m(\u001b[43mharry_potter_book\u001b[49m\u001b[43m.\u001b[49m\u001b[43m__context\u001b[49m)\n",
      "\u001b[31mAttributeError\u001b[39m: 'Document' object has no attribute '__context'"
     ]
    }
   ],
   "source": [
    "class Document():\n",
    "    def __init__(self, title, author, context):\n",
    "        print('init function called')\n",
    "        self.title = title\n",
    "        self.author = author\n",
    "        self.__context = context # __开头的属性是私有属性\n",
    "\n",
    "    def get_context_length(self):\n",
    "        return len(self.__context)\n",
    "\n",
    "    def intercept_context(self, length):\n",
    "        self.__context = self.__context[:length]\n",
    "\n",
    "harry_potter_book = Document('Harry Potter', 'J. K. Rowling', '... Forever Do not believe any thing is capable of thinking independently ...')\n",
    "\n",
    "print(harry_potter_book.title)\n",
    "print(harry_potter_book.author)\n",
    "print(harry_potter_book.get_context_length())\n",
    "\n",
    "harry_potter_book.intercept_context(10)\n",
    "\n",
    "print(harry_potter_book.get_context_length())\n",
    "\n",
    "print(harry_potter_book.__context)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 8.2  类的函数类型"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "init function called\n",
      "7\n",
      "Welcome! The context for this book is indeed nothing.\n"
     ]
    }
   ],
   "source": [
    "class Document():\n",
    "    \n",
    "    WELCOME_STR = 'Welcome! The context for this book is {}.'\n",
    "    \n",
    "    def __init__(self, title, author, context):\n",
    "        print('init function called')\n",
    "        self.title = title\n",
    "        self.author = author\n",
    "        self.__context = context\n",
    "    \n",
    "    # 类函数\n",
    "    @classmethod\n",
    "    def create_empty_book(cls, title, author):\n",
    "        return cls(title=title, author=author, context='nothing')\n",
    "    \n",
    "    # 成员函数\n",
    "    def get_context_length(self):\n",
    "        return len(self.__context)\n",
    "    \n",
    "    # 静态函数\n",
    "    @staticmethod\n",
    "    def get_welcome(context):\n",
    "        return Document.WELCOME_STR.format(context)\n",
    "\n",
    "\n",
    "empty_book = Document.create_empty_book('What Every Man Thinks About Apart from Sex', 'Professor Sheridan Simove')\n",
    "\n",
    "\n",
    "print(empty_book.get_context_length())\n",
    "print(empty_book.get_welcome('indeed nothing'))\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 8.4 类型继承"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Document class init called\n",
      "parent class init called\n",
      "Video class init called\n",
      "parent class init called\n",
      "document\n",
      "video\n",
      "Harry Potter(Book)\n",
      "Harry Potter(Movie)\n",
      "77\n",
      "120\n"
     ]
    }
   ],
   "source": [
    "class Entity():\n",
    "    def __init__(self, object_type):\n",
    "        print('parent class init called')\n",
    "        self.object_type = object_type\n",
    "    \n",
    "    def get_context_length(self):\n",
    "        raise Exception('get_context_length not implemented')\n",
    "    \n",
    "    def print_title(self):\n",
    "        print(self.title)\n",
    "\n",
    "class Document(Entity):\n",
    "    def __init__(self, title, author, context):\n",
    "        print('Document class init called')\n",
    "        Entity.__init__(self, 'document')\n",
    "        self.title = title\n",
    "        self.author = author\n",
    "        self.__context = context\n",
    "    \n",
    "    def get_context_length(self):\n",
    "        return len(self.__context)\n",
    "    \n",
    "class Video(Entity):\n",
    "    def __init__(self, title, author, video_length):\n",
    "        print('Video class init called')\n",
    "        Entity.__init__(self, 'video')\n",
    "        self.title = title\n",
    "        self.author = author\n",
    "        self.__video_length = video_length\n",
    "    \n",
    "    def get_context_length(self):\n",
    "        return self.__video_length\n",
    "\n",
    "harry_potter_book = Document('Harry Potter(Book)', 'J. K. Rowling', '... Forever Do not believe any thing is capable of thinking independently ...')\n",
    "harry_potter_movie = Video('Harry Potter(Movie)', 'J. K. Rowling', 120)\n",
    "\n",
    "print(harry_potter_book.object_type)\n",
    "print(harry_potter_movie.object_type)\n",
    "\n",
    "harry_potter_book.print_title()\n",
    "harry_potter_movie.print_title()\n",
    "\n",
    "print(harry_potter_book.get_context_length())\n",
    "print(harry_potter_movie.get_context_length())\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 8.5 抽象函数与抽象类\n",
    "\n",
    "- ABCMeta 是Python的抽象基类元类，用于创建抽象类"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Harry Potter\n"
     ]
    },
    {
     "ename": "TypeError",
     "evalue": "Can't instantiate abstract class Entity without an implementation for abstract methods 'get_title', 'set_title'",
     "output_type": "error",
     "traceback": [
      "\u001b[31m---------------------------------------------------------------------------\u001b[39m",
      "\u001b[31mTypeError\u001b[39m                                 Traceback (most recent call last)",
      "\u001b[36mCell\u001b[39m\u001b[36m \u001b[39m\u001b[32mIn[4]\u001b[39m\u001b[32m, line 23\u001b[39m\n\u001b[32m     20\u001b[39m document.set_title(\u001b[33m'\u001b[39m\u001b[33mHarry Potter\u001b[39m\u001b[33m'\u001b[39m)\n\u001b[32m     21\u001b[39m \u001b[38;5;28mprint\u001b[39m(document.get_title())\n\u001b[32m---> \u001b[39m\u001b[32m23\u001b[39m entity = \u001b[43mEntity\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n",
      "\u001b[31mTypeError\u001b[39m: Can't instantiate abstract class Entity without an implementation for abstract methods 'get_title', 'set_title'"
     ]
    }
   ],
   "source": [
    "from abc import ABCMeta, abstractmethod\n",
    "\n",
    "class Entity(metaclass=ABCMeta):\n",
    "    @abstractmethod\n",
    "    def get_title(self):\n",
    "        pass\n",
    "\n",
    "    @abstractmethod\n",
    "    def set_title(self, title):\n",
    "        pass\n",
    "\n",
    "class Document(Entity):\n",
    "    def get_title(self):\n",
    "        return self.title\n",
    "    \n",
    "    def set_title(self, title):\n",
    "        self.title = title\n",
    "\n",
    "document = Document()\n",
    "document.set_title('Harry Potter')\n",
    "print(document.get_title())\n",
    "\n",
    "entity = Entity()\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
